package jnpf.engine.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jnpf.base.ActionResult;
import jnpf.base.UserInfo;
import jnpf.base.controller.SuperController;
import jnpf.base.vo.PageListVO;
import jnpf.base.vo.PaginationVO;
import jnpf.constant.MsgCode;
import jnpf.engine.entity.*;
import jnpf.engine.model.flowbefore.FlowUserListModel;
import jnpf.engine.model.flowcomment.FlowCommentForm;
import jnpf.engine.model.flowcomment.FlowCommentInfoVO;
import jnpf.engine.model.flowcomment.FlowCommentListVO;
import jnpf.engine.model.flowcomment.FlowCommentPagination;
import jnpf.engine.model.flowengine.FlowModel;
import jnpf.engine.model.flowengine.shuntjson.childnode.MsgConfig;
import jnpf.engine.model.flowengine.shuntjson.childnode.Properties;
import jnpf.engine.model.flowengine.shuntjson.nodejson.ChildNodeList;
import jnpf.engine.model.flowmessage.FlowMsgModel;
import jnpf.engine.service.FlowCommentService;
import jnpf.engine.service.FlowTaskNodeService;
import jnpf.engine.util.*;
import jnpf.exception.DataException;
import jnpf.exception.WorkFlowException;
import jnpf.permission.entity.UserEntity;
import jnpf.permission.service.UserService;
import jnpf.util.*;
import org.flowable.engine.HistoryService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 流程评论
 *
 * @author JNPF开发平台组
 * @version V3.1.0
 * @copyright 引迈信息技术有限公司
 */
@Tag(name = "流程评论", description = "Comment")
@RestController
@RequestMapping("/api/workflow/Engine/FlowComment")
public class FlowCommentController extends SuperController<FlowCommentService, FlowCommentEntity> {


    @Autowired
    private ServiceAllUtil serviceUtil;
    @Autowired
    private UserProvider userProvider;
    @Autowired
    private FlowCommentService flowCommentService;
    @Autowired
    private FlowTaskNodeService flowTaskNodeService;
    @Autowired
    private UserService userService;
    @Autowired
    private FlowTaskUtil flowTaskUtil;
    @Autowired
    private FlowMsgUtil flowMsgUtil;

    /**
     * 获取流程评论列表
     *
     * @param pagination 分页模型
     * @return
     */
    @Operation(summary = "获取流程评论列表")
    @GetMapping
    public ActionResult<PageListVO<FlowCommentListVO>> list(FlowCommentPagination pagination) {
        List<FlowCommentEntity> list = flowCommentService.getlist(pagination);
        List<FlowCommentListVO> listVO = new ArrayList<>();
        List<String> userId = list.stream().map(t -> t.getCreatorUserId()).collect(Collectors.toList());
        UserInfo userInfo = userProvider.get();
        List<UserEntity> userName = serviceUtil.getUserName(userId);
        for (FlowCommentEntity flowCommentEntity : list) {
            FlowCommentListVO vo = JsonUtil.getJsonToBean(flowCommentEntity, FlowCommentListVO.class);
            UserEntity userEntity = userName.stream().filter(t -> t.getId().equals(flowCommentEntity.getCreatorUserId())).findFirst().orElse(null);
            if(flowCommentEntity.getCreatorUserId().equals(userInfo.getUserId()) && !"1".equals(String.valueOf(flowCommentEntity.getDeleteShow()))) {
                vo.setIsDel(1); //1-删除按钮显示
            }else if("1".equals(String.valueOf(flowCommentEntity.getDeleteShow()))) {
                vo.setIsDel(2); //1-删除按钮显示
                vo.setText("该评论已被删除");
            }else{
                vo.setIsDel(0);
            }
            vo.setCreatorUser(userEntity != null ? userEntity.getRealName() + "/" + userEntity.getAccount() : "");
            vo.setCreatorUserHeadIcon(userEntity != null ? UploaderUtil.uploaderImg(userEntity.getHeadIcon()) : vo.getCreatorUserHeadIcon());
            if(StringUtil.isNotEmpty(flowCommentEntity.getReplyId())) {
                FlowCommentEntity replyEntity = list.stream().filter(t-> t.getId().equals(flowCommentEntity.getReplyId())).findFirst().orElse(null);
                if(replyEntity == null) {
                    replyEntity = flowCommentService.getInfo(flowCommentEntity.getReplyId());
                }
                if(replyEntity != null) {
                    FlowCommentEntity finalReplyEntity = replyEntity;
                    UserEntity replyUserEntity = userName.stream().filter(t -> t.getId().equals(finalReplyEntity.getCreatorUserId())).findFirst().orElse(null);
                    vo.setReplyUser(userEntity != null ? replyUserEntity.getRealName() + "/" + replyUserEntity.getAccount() : "");
                    vo.setReplyText(("1".equals(String.valueOf(replyEntity.getDeleteShow())) || "1".equals(String.valueOf(replyEntity.getDeleteMark()))) ? "该评论已被删除": replyEntity.getText());
                }
            }
            listVO.add(vo);
        }
        PaginationVO vo = JsonUtil.getJsonToBean(pagination, PaginationVO.class);
        return ActionResult.page(listVO, vo);
    }

    /**
     * 获取流程评论信息
     *
     * @param id 主键
     * @return
     */
    @Operation(summary = "获取流程评论信息")
    @GetMapping("/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
    })
    public ActionResult<FlowCommentInfoVO> info(@PathVariable("id") String id) {
        FlowCommentEntity entity = flowCommentService.getInfo(id);
        FlowCommentInfoVO vo = JsonUtil.getJsonToBean(entity, FlowCommentInfoVO.class);
        return ActionResult.success(vo);
    }

    /**
     * 新建流程评论
     *
     * @param commentForm 流程评论模型
     * @return
     */
    @Operation(summary = "新建流程评论")
    @PostMapping
    @Parameters({
            @Parameter(name = "commentForm", description = "流程评论模型", required = true),
    })
    public ActionResult create(@RequestBody @Valid FlowCommentForm commentForm) throws DataException, WorkFlowException {
        FlowCommentEntity entity = JsonUtil.getJsonToBean(commentForm, FlowCommentEntity.class);
        flowCommentService.create(entity);

        //发送提醒消息
        this.sendCommentMsg(entity);

        return ActionResult.success(MsgCode.SU002.get());
    }

    /**
     * 更新流程评论
     *
     * @param id          主键
     * @param commentForm 流程评论模型
     * @return
     */
    @Operation(summary = "更新流程评论")
    @PutMapping("/{id}")
    @Parameters({
            @Parameter(name = "commentForm", description = "流程评论模型", required = true),
            @Parameter(name = "id", description = "主键", required = true),
    })
    public ActionResult update(@PathVariable("id") String id, @RequestBody @Valid FlowCommentForm commentForm) throws DataException {
        FlowCommentEntity info = flowCommentService.getInfo(id);
        if (info != null) {
            FlowCommentEntity entity = JsonUtil.getJsonToBean(commentForm, FlowCommentEntity.class);
            entity.setDeleteShow(info.getDeleteShow());
            flowCommentService.update(id, entity);
            return ActionResult.success(MsgCode.SU004.get());
        }
        return ActionResult.fail(MsgCode.FA002.get());
    }

    /**
     * 删除流程评论
     *
     * @param id 主键
     * @return
     */
    @Operation(summary = "删除流程评论")
    @DeleteMapping("/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
    })
    @Transactional
    public ActionResult delete(@PathVariable("id") String id) {
        FlowCommentEntity entity = flowCommentService.getInfo(id);
        if (entity.getCreatorUserId().equals(userProvider.get().getUserId())) {
            UserInfo userInfo = userProvider.get();
            boolean isDeleteShow = false;
            ChildNodeList childNodeList = this.getCommentChildNodeList(entity.getTaskId());
            if(childNodeList != null && childNodeList.getProperties().getIsShowDelComment() != null && childNodeList.getProperties().getIsShowDelComment()) {
                isDeleteShow = true;
            }
            if(isDeleteShow) {
                entity.setDeleteShow(1);
                entity.setDeleteTime(new Date());
                entity.setDeleteUserId(userInfo.getUserId());
                flowCommentService.updateById(entity);
            }else{
                entity.setDeleteMark(1);
                entity.setDeleteTime(new Date());
                entity.setDeleteUserId(userInfo.getUserId());
                flowCommentService.updateById(entity);
//                List<FlowCommentEntity> deleteList = new ArrayList<>();
//                deleteList.add(entity);
//                List<String> deleteIdList = deleteList.stream().map(t-> t.getId()).collect(Collectors.toList());
//                this.getDeleteList(deleteList, deleteIdList);
//                for(FlowCommentEntity each : deleteList) {
//                    flowCommentService.delete(each);
//                }
            }
            return ActionResult.success(MsgCode.SU003.get());
        }
        return ActionResult.success(MsgCode.FA003.get());
    }

    //递归查询下级
    private void getDeleteList(List<FlowCommentEntity> allDeleteList, List<String> parentIdList) {
        if(parentIdList == null || parentIdList.isEmpty()) {
            return;
        }
        QueryWrapper<FlowCommentEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().in(FlowCommentEntity::getReplyId, parentIdList);
        List<FlowCommentEntity> childrenList = flowCommentService.list(queryWrapper);
        if(childrenList == null || childrenList.isEmpty()) {
            return;
        }
        parentIdList = childrenList.stream().map(t-> t.getId()).collect(Collectors.toList());
        allDeleteList.addAll(childrenList);
        this.getDeleteList(allDeleteList, parentIdList);
    }


    private ChildNodeList getCommentChildNodeList(String taskId) {
        if(StringUtil.isEmpty(taskId)) {
            return null;
        }
        QueryWrapper<FlowTaskNodeEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(FlowTaskNodeEntity::getTaskId, taskId);
        queryWrapper.lambda().eq(FlowTaskNodeEntity::getNodeType, FlowNature.NodeStart);
        queryWrapper.lambda().orderByDesc(FlowTaskNodeEntity::getCreatorTime);
        queryWrapper.lambda().select(FlowTaskNodeEntity::getNodePropertyJson);
        List<FlowTaskNodeEntity> startNodeList = flowTaskNodeService.list(queryWrapper);
        if(startNodeList != null && !startNodeList.isEmpty()) {
            FlowTaskNodeEntity flowNode = startNodeList.get(0);
            ChildNodeList childNodeList = JsonUtil.getJsonToBean(flowNode.getNodePropertyJson(), ChildNodeList.class);
            return childNodeList;
        }
        return null;
    }

    //发送提醒消息
    private void sendCommentMsg(FlowCommentEntity flowCommentEntity) throws WorkFlowException {
        //发消息
        UserInfo userInfo = userProvider.get();
        //不包含@{ 且 回复ID为空 （不发消息）
        if((StringUtil.isEmpty(flowCommentEntity.getText()) || !flowCommentEntity.getText().contains("@{")) && StringUtil.isEmpty(flowCommentEntity.getReplyId())) {
            return;
        }
        HistoryService historyService = SpringContextHolder.getBean(HistoryService.class);
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(flowCommentEntity.getTaskId()).singleResult();
//        ChildNodeList startChildNodeList = this.getCommentChildNodeList(flowCommentEntity.getTaskId());
//        if(startChildNodeList == null ||  startChildNodeList.getProperties() == null || startChildNodeList.getProperties().getCommentMsgConfig() == null || startChildNodeList.getProperties().getCommentMsgConfig().getOn() == null) {
//            return;
//        }
        Properties firstNodeProperty = BpmnModelUtils.getFirstNodeProperty(historicProcessInstance.getProcessDefinitionId());
        MsgConfig commentMsgConfig = firstNodeProperty.getCommentMsgConfig();
        if(commentMsgConfig.getOn() != 1 && commentMsgConfig.getOn() != 3) {
            return;
        }
        Set<String> userIdSet = new HashSet<>();
        //回复
        if(StringUtil.isNotEmpty(flowCommentEntity.getReplyId())) {
            FlowCommentEntity replyEntity = flowCommentService.getInfo(flowCommentEntity.getReplyId());
            if(replyEntity != null && StringUtil.isNotEmpty(replyEntity.getCreatorUserId())) {
                userIdSet.add(replyEntity.getCreatorUserId());
            }
        }
        //@
        if(StringUtil.isNotEmpty(flowCommentEntity.getText()) && flowCommentEntity.getText().contains("@{")) {
            String[] textArray = flowCommentEntity.getText().split("@\\{");
            List<String> accountList = new ArrayList<>();
            for(int i = 0; i<textArray.length; i ++) {
                if(i == 0) {
                    continue;
                }
                if(!textArray[i].trim().contains("}")) {
                    continue;
                }
                String nameAndAccount = textArray[i].substring(0, textArray[i].indexOf("}"));
                if(nameAndAccount.contains("/") && !nameAndAccount.trim().startsWith("/") && !nameAndAccount.trim().endsWith("/")) {
                    String[] nameAndAccountArray = nameAndAccount.split("/");
                    if(nameAndAccountArray.length != 2) {
                        continue;
                    }
                    accountList.add(nameAndAccountArray[1].trim());
                }
            }
            if(accountList != null && !accountList.isEmpty()) {
                QueryWrapper<UserEntity> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().in(UserEntity::getAccount, accountList);
                queryWrapper.lambda().select(UserEntity::getId);
                List<UserEntity> list = userService.list(queryWrapper);
                userIdSet.addAll(list.stream().map(t-> t.getId()).collect(Collectors.toSet()));
            }
        }
        //过滤自己
        Set<String> finalUserIdSet = userIdSet;
        userIdSet = userIdSet.stream().filter(t-> !finalUserIdSet.contains(userInfo.getUserId())).collect(Collectors.toSet());

        if(userIdSet.isEmpty()) {
            return;
        }
        FlowUserListModel flowUserListModel = flowTaskUtil.getTaskUserList(flowCommentEntity.getTaskId());
        userIdSet.retainAll(flowUserListModel.getAllUserIdList()); //取交集
        if(userIdSet.isEmpty()) {
            return;
        }

        Set<String> noAddUserIdList = new HashSet<>(userIdSet);
        //审批人
        List<FlowTaskOperatorEntity> operatorList = new ArrayList<>(); //审批人
//        List<FlowOperatorUserEntity> operatorUserList = new ArrayList<>(); //依次审批人
        List<FlowTaskCirculateEntity> circulateList = new ArrayList<>(); //抄送人
        List<FlowTaskOperatorRecordEntity> operatorRecordList = new ArrayList<>(); //已办数据
        String startHandId = null; //发起人

        //审批人
        if(!noAddUserIdList.isEmpty()) {
            for(FlowTaskOperatorEntity each : flowUserListModel.getOperatorList()) {
                if(noAddUserIdList.contains(each.getHandleId())) {
                    operatorList.add(each);
                    noAddUserIdList.remove(each.getHandleId());
                }
            }
        }
        //依次审批人
//        if(!noAddUserIdList.isEmpty()) {
//            for (FlowOperatorUserEntity each : flowUserListModel.getOperatorUserList()) {
//                if (noAddUserIdList.contains(each.getHandleId())) {
//                    operatorUserList.add(each);
//                    noAddUserIdList.remove(each.getHandleId());
//                }
//            }
//        }
        //抄送人
        if(!noAddUserIdList.isEmpty()) {
            for (FlowTaskCirculateEntity each : flowUserListModel.getCirculateList()) {
                if (noAddUserIdList.contains(each.getObjectId())) {
                    circulateList.add(each);
                    noAddUserIdList.remove(each.getObjectId());
                }
            }
        }
        //发起人
        if(!noAddUserIdList.isEmpty()) {
            if(noAddUserIdList.contains(flowUserListModel.getFlowTask().getCreatorUserId())) {
                startHandId = flowUserListModel.getFlowTask().getCreatorUserId();
            }
        }

        //已办记录
        if(!noAddUserIdList.isEmpty()) {
            for (FlowTaskOperatorRecordEntity each : flowUserListModel.getOperatorRecordList()) {
                if(noAddUserIdList.contains(each.getHandleId())) {
                    operatorRecordList.add(each);
                    noAddUserIdList.remove(each.getHandleId());
                }
            }
        }

        //节点集合
        QueryWrapper<FlowTaskNodeEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(FlowTaskNodeEntity::getTaskId, flowCommentEntity.getTaskId());
        queryWrapper.lambda().eq(FlowTaskNodeEntity::getState, 0);
        queryWrapper.lambda().orderByDesc(FlowTaskNodeEntity::getCreatorTime);
        List<FlowTaskNodeEntity> nodeList = flowTaskNodeService.list(queryWrapper);
        //构造消息
        FlowMsgModel flowMsgModel = new FlowMsgModel();
//        flowMsgModel.setTaskEntity(flowUserListModel.getFlowTask());
//        flowMsgModel.setNodeList(nodeList);
        flowMsgModel.setOperatorList(operatorList);
        flowMsgModel.setCirculateList(circulateList);
        flowMsgModel.setOperatorRecordList(operatorRecordList);
        flowMsgModel.setStartHandId(startHandId);
        FlowModel flowModel = new FlowModel();
        flowModel.setUserInfo(userInfo);
        flowMsgModel.setFlowModel(flowModel);
        flowMsgModel.setWait(false);
        flowMsgModel.setComment(true);
        //发送消息
        flowMsgUtil.message(flowMsgModel);
    }

}
